package dbz.domain;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;

import dbz.domain.attack.Attack;
import dbz.domain.fighter.status.FighterStatus;

public class Fighter extends Card {

	

	private String name;
	private Health health;
	private FighterStatus status;
	private Stack<Ki> ki;
	private Map<String, Attack> attacks;

	public Fighter(String name, Health health, FighterStatus status, Collection<Attack> attacks) {
		this.name = name;
		this.health = health;
		this.status = status;
		this.ki = new Stack<Ki>();
		this.attacks = new HashMap<String, Attack>();
		initAttacks(attacks);
		
	}

	private void initAttacks(Collection<Attack> attacks) {
		for(Attack attack : attacks) {
			attack.teach(this);
			this.attacks.put(attack.getName(), attack);
		}
	}

	public void takeDamage(Integer hitPoints) {
		health.takeDamage(hitPoints);
		
	}

	public Integer getRemainingHitPoints() {
		return health.getRemainingHitPoints();
	}
	
	public void learnAttack(Attack attack) {
		attack.teach(this);
		attacks.put(attack.getName(), attack);
	}
	
	public void attack(String attackName, Fighter defensiveFighter) {
		status.attack(attacks.get(attackName), defensiveFighter);
	}

	public void powerUp(Ki ki) {
		this.ki.push(ki);		
	}

	public Boolean isAbleToAttack() {
		
		return status.isAbleToAttack() && atLeastOneAttackConditionsAreSatisfied();
		
	}

	private Boolean atLeastOneAttackConditionsAreSatisfied() {
		return CollectionUtils.countMatches(attacks.values(), new AttackConditionsSatisfied()) > 0;
	}
	
	public class AttackConditionsSatisfied implements Predicate {

		@Override
		public boolean evaluate(Object arg0) {
			return ((Attack)arg0).areConditionsSatisfied();
		}

	}

	public Integer getKiLevel() {
		return ki.size();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Health getHealth() {
		return health;
	}

	public void setHealth(Health health) {
		this.health = health;
	}

	public FighterStatus getStatus() {
		return status;
	}

	public void setStatus(FighterStatus status) {
		this.status = status;
	}

	public Stack<Ki> getKi() {
		return ki;
	}

	public void setKi(Stack<Ki> ki) {
		this.ki = ki;
	}

	public Map<String, Attack> getAttacks() {
		return attacks;
	}

	public void setAttacks(Map<String, Attack> attacks) {
		this.attacks = attacks;
	}
	
}
